import "reflect-metadata";

export const MapKey = "targetProperty";
export function Mapper(property, clazz?) {
  return Reflect.metadata(MapKey, { property, clazz });
}

Mapper.map = function (target, source) {
  const keys = Object.keys(target);
  keys.forEach((key) => {
    const data = Reflect.getMetadata(MapKey, target, key);
    const property = data?.property;
    const clazz = data?.clazz;

    if (property) {
      const propertys = property.split(",");
      if ((propertys.length == 1)) {
        setValue(target, key, source[propertys[0]], clazz);
      } else {
        
        setCollectValue(target, key, source, propertys, clazz);
      }
    } else if (source[key]) {
      target[key] = source[key];
    }
  });
};

function setValue(target, key, val, clazz?) {
  if (Array.isArray(target[key]) && clazz) {
    target[key] = val?.map((item) => {
      return new clazz(item);
    });
  } else if (clazz) {
    target[key] = new clazz(val);
  } else {
    target[key] = val;
  }
}

function setCollectValue(target, key, source, propertys, clazz?) {
  let val = {};
  propertys?.forEach((propertyName) => {
    const propertyKey = propertyName || key;
    setValue(val, propertyKey, source[propertyKey], clazz);
  });
  target[key] = val;
}
